package cn.broadsense.common.utils.uuid;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import cn.broadsense.common.utils.DateUtils;
import cn.broadsense.common.utils.StringUtils;
import cn.broadsense.common.utils.spring.SpringUtils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;

/**
 * @author ruoyi 序列生成类
 */
public class Seq {

    /**
     * 生成序号前缀
     */
    private static final String S_NUM_KEY = "vt:s:num:%s:%s";
    // 通用序列类型
    public static final String commSeqType = "COMMON";

    // 上传序列类型
    public static final String uploadSeqType = "UPLOAD";

    // 通用接口序列数
    private static AtomicInteger commSeq = new AtomicInteger(1);

    // 上传接口序列数
    private static AtomicInteger uploadSeq = new AtomicInteger(1);

    // 机器标识
    private static final String machineCode = "A";

    /**
     * 获取通用序列号
     *
     * @return 序列值
     */
    public static String getId() {
        return getId(commSeqType);
    }

    /**
     * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
     *
     * @return 序列值
     */
    public static String getId(String type) {
        AtomicInteger atomicInt = commSeq;
        if (uploadSeqType.equals(type)) {
            atomicInt = uploadSeq;
        }
        return getId(atomicInt, 3);
    }

    /**
     * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
     *
     * @param atomicInt 序列数
     * @param length    数值长度
     * @return 序列值
     */
    public static String getId(AtomicInteger atomicInt, int length) {
        String result = DateUtils.dateTimeNow();
        result += machineCode;
        result += getSeq(atomicInt, length);
        return result;
    }

    /**
     * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数
     *
     * @return 序列值
     */
    private synchronized static String getSeq(AtomicInteger atomicInt, int length) {
        // 先取值再+1
        int value = atomicInt.getAndIncrement();

        // 如果更新后值>=10 的 (length)幂次方则重置为1
        int maxSeq = (int) Math.pow(10, length);
        if (atomicInt.get() >= maxSeq) {
            atomicInt.set(1);
        }
        // 转字符串，用0左补齐
        return StringUtils.padl(value, length);
    }

    /**
     * 生成数据项编码
     *
     * @return
     */
    public static String generateDataItemCode() {
        return generate("BH-");
    }


    public static String generate(String prefix) {
        Date date = new Date();
        DateTime endOfDay = DateUtil.endOfDay(date);
        String formatDate = DateUtil.format(date, DatePattern.PURE_DATE_PATTERN);
        String key = String.format(S_NUM_KEY, prefix, formatDate);
        //RedisAtomicLong为原子类，根据传入的key和redis链接工厂创建原子类
        RedisAtomicLong counter = new RedisAtomicLong(key, ((RedisTemplate) SpringUtils.getBean("redisTemplate")).getConnectionFactory());
        //设置过期时间
        counter.expireAt(endOfDay);
        //返回redis中key的值
        long seq = counter.incrementAndGet();
        String sequence = org.apache.commons.lang3.StringUtils.leftPad(seq + "", 4, "0");
        return prefix + formatDate + sequence;
    }
}
